home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / OpenGL 1.0 SDK / Source / Examples / aux / backtrace / Unitdisk.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-18  |  20.6 KB  |  843 lines  |  [TEXT/CWIE]

  1. /*
  2.  * (c) Copyright 1993, 1994, 1995, 1996 Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED 
  4.  * Permission to use, copy, modify, and distribute this software for 
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that 
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission. 
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  * 
  25.  * US Government Users Restricted Rights 
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. #include "glu.h"
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <math.h>
  41.  
  42. #include "Unitdisk.h"
  43.  
  44. #define M_PI  3.14159265359
  45.  
  46. const float fudge = .000001;
  47. const float M_2PI = 2.0 * M_PI;
  48.  
  49. Unitdisk::Unitdisk()
  50. {
  51.   rdivisions = 3;
  52.   tdivisions = 10;
  53.   points = normals = NULL;
  54.   colors = NULL;
  55.   points_size = normals_size = colors_size = 0;
  56.   angle = M_PI;
  57.   zaxis[0] = 0;
  58.   zaxis[1] = 0;
  59.   zaxis[2] = 1;
  60.  
  61.   still_in_xy = 1;
  62.  
  63.   sintable = costable = NULL;
  64. }
  65.  
  66. Unitdisk::~Unitdisk()
  67. {
  68. }
  69.  
  70. void Unitdisk::draw()
  71. {
  72.   if (points == NULL) return;
  73.   glNormal3f(0, 0, 1);
  74.   if (colors == NULL) draw_nocolors();
  75.   else if (normals == NULL) draw_colors_nonormals();
  76.   else draw_colors_normals();
  77. }
  78.  
  79. void Unitdisk::draw_nocolors()
  80. {
  81.   int r, t, p1, p2;
  82.   int has_n;
  83.  
  84.   has_n = (normals != NULL);
  85.  
  86.   for (t = 1; t < tdivisions; t++) {
  87.     glBegin(GL_QUAD_STRIP);
  88.     p1 = t * (rdivisions + 1);
  89.     p2 = (t - 1) * (rdivisions + 1);
  90.     for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  91.       if (has_n) glNormal3fv(normals[p1].pt);
  92.       glTexCoord2fv(points[p1].pt);
  93.       glVertex3fv(points[p1].pt);
  94.       if (has_n) glNormal3fv(normals[p2].pt);
  95.       glTexCoord2fv(points[p2].pt);
  96.       glVertex3fv(points[p2].pt);
  97.     } 
  98.     glEnd(); 
  99.   }
  100.   
  101.   glBegin(GL_QUAD_STRIP); 
  102.   p1 = 0;
  103.   p2 = (rdivisions + 1) * (tdivisions - 1);
  104.   for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  105.     if (has_n) glNormal3fv(normals[p1].pt);
  106.     glTexCoord2fv(points[p1].pt);
  107.     glVertex3fv(points[p1].pt);
  108.     if (has_n) glNormal3fv(normals[p2].pt);
  109.     glTexCoord2fv(points[p2].pt);
  110.     glVertex3fv(points[p2].pt);
  111.   }
  112.   glEnd();
  113. }
  114.  
  115. void Unitdisk::draw_colors_nonormals()
  116. {  
  117.   int r, t, p1, p2;
  118.  
  119.   for (t = 1; t < tdivisions; t++) {
  120.     glBegin(GL_QUAD_STRIP);
  121.     p1 = t * (rdivisions + 1);
  122.     p2 = (t - 1) * (rdivisions + 1);
  123.     for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  124.       glColor4fv(colors[p1].c);
  125.       glTexCoord2fv(points[p1].pt);
  126.       glVertex3fv(points[p1].pt);
  127.       glColor4fv(colors[p2].c);
  128.       glTexCoord2fv(points[p2].pt);
  129.       glVertex3fv(points[p2].pt);
  130.     } 
  131.     glEnd(); 
  132.   }
  133.   
  134.   glBegin(GL_QUAD_STRIP); 
  135.   p1 = 0;
  136.   p2 = (rdivisions + 1) * (tdivisions - 1);
  137.   for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  138.     glColor4fv(colors[p1].c);
  139.     glTexCoord2fv(points[p1].pt);
  140.     glVertex3fv(points[p1].pt);
  141.     glColor4fv(colors[p2].c);
  142.     glTexCoord2fv(points[p2].pt);
  143.     glVertex3fv(points[p2].pt);
  144.   }
  145.   glEnd();
  146. }
  147.  
  148. void Unitdisk::draw_colors_normals()
  149. {
  150.   int r, t, p1, p2;
  151.  
  152.   for (t = 1; t < tdivisions; t++) {
  153.     glBegin(GL_QUAD_STRIP);
  154.     p1 = t * (rdivisions + 1);
  155.     p2 = (t - 1) * (rdivisions + 1);
  156.     for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  157.       glColor4fv(colors[p1].c);
  158.       glNormal3fv(normals[p1].pt);
  159.       glTexCoord2fv(points[p1].pt);
  160.       glVertex3fv(points[p1].pt);
  161.       glColor4fv(colors[p2].c);
  162.       glNormal3fv(normals[p2].pt);
  163.       glTexCoord2fv(points[p2].pt);
  164.       glVertex3fv(points[p2].pt);
  165.     } 
  166.     glEnd(); 
  167.   }
  168.   
  169.   glBegin(GL_QUAD_STRIP); 
  170.   p1 = 0;
  171.   p2 = (rdivisions + 1) * (tdivisions - 1);
  172.   for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  173.     glColor4fv(colors[p1].c);
  174.     glNormal3fv(normals[p1].pt);
  175.     glTexCoord2fv(points[p1].pt);
  176.     glVertex3fv(points[p1].pt);
  177.     glColor4fv(colors[p2].c);
  178.     glNormal3fv(normals[p2].pt);
  179.     glTexCoord2fv(points[p2].pt);
  180.     glVertex3fv(points[p2].pt);
  181.   }
  182.   glEnd();
  183. }
  184.  
  185. void Unitdisk::draw_by_perimeter(int pass_colors, int pass_norms, 
  186.                  int pass_tex)
  187. {
  188.   int i, index, r = rdivisions + 1;
  189.  
  190.   if (points == NULL) return;
  191.   if (pass_colors && colors == NULL) {
  192.     fprintf(stderr, "Warning:  No colors to draw in Unitdisk.c++");
  193.     pass_colors = 0;
  194.   }
  195.   if (pass_norms && normals == NULL) {
  196.     fprintf(stderr, "Warning:  No normals to draw in Unitdisk.c++");
  197.     pass_norms = 0;
  198.   }
  199.   glBegin(GL_POLYGON);
  200.   for (i = 0, index = rdivisions; i < tdivisions; i++, index += r) {
  201.     if (pass_colors) glColor4fv(colors[index].c);
  202.     if (pass_norms) glNormal3fv(normals[index].pt);
  203.     if (pass_tex) glTexCoord2fv(points[index].pt);
  204.     glVertex3fv(points[index].pt);
  205.   }
  206.   glEnd();
  207.   
  208. }
  209.  
  210. void Unitdisk::set_angle(float new_angle)
  211. {
  212.   angle = new_angle;
  213. }
  214.  
  215. GLfloat Unitdisk::get_angle()
  216. {
  217.   return angle;
  218. }
  219.  
  220. GLfloat Unitdisk::get_radius()
  221. {
  222.   return cos((M_PI - angle) / 2.0);
  223. }
  224.  
  225. void Unitdisk::set_divisions(int new_rdivisions, int new_tdivisions)
  226. {
  227.   if (tdivisions != new_tdivisions) {
  228.     delete sintable;
  229.     delete costable;
  230.     sintable = costable = NULL;
  231.   }
  232.   if (tdivisions != new_tdivisions || rdivisions != new_rdivisions) {
  233.     rdivisions = new_rdivisions;
  234.     tdivisions = new_tdivisions;
  235.     free_points();
  236.     free_normals();
  237.     free_colors();
  238.   }
  239. }
  240.   
  241. int Unitdisk::get_rdivisions()
  242. {
  243.   return rdivisions;
  244. }
  245.  
  246. int Unitdisk::get_tdivisions()
  247. {
  248.   return tdivisions;
  249. }
  250.  
  251. void Unitdisk::alloc_points()
  252. {
  253.   int npoints = get_npoints();
  254.   if (npoints > points_size) {
  255.     delete points;
  256.     points = new Point_b[npoints];
  257.     points_size = npoints;
  258.   }
  259. }
  260.  
  261. void Unitdisk::alloc_normals()
  262. {
  263.   int npoints = get_npoints();
  264.   if (npoints > normals_size) {
  265.     delete normals;
  266.     normals = new Point_b[npoints];
  267.     normals_size = npoints;
  268.   }
  269. }
  270.  
  271. void Unitdisk::alloc_points_normals()
  272. {
  273.   alloc_points();
  274.   alloc_normals();
  275. }
  276.  
  277. void Unitdisk::free_points() 
  278. {
  279.   delete points;
  280.   points = NULL;
  281.   points_size = 0;
  282. }
  283.  
  284. void Unitdisk::free_normals()
  285. {
  286.   delete normals;
  287.   normals = NULL;
  288.   normals_size = 0;
  289. }
  290.  
  291. void Unitdisk::free_points_normals()
  292. {
  293.   free_points();
  294.   free_normals();
  295. }
  296.  
  297. void Unitdisk::fill_points()
  298. {
  299.   alloc_points();
  300.   fill_either(points);
  301. }
  302.  
  303. void Unitdisk::fill_normals()
  304. {
  305.   alloc_normals();
  306.   fill_either(normals);
  307. }
  308.  
  309. void Unitdisk::fill_points_normals()
  310. {
  311.   alloc_points();
  312.   alloc_normals();
  313.   fill_either(points);
  314.   fill_either(normals);
  315. }
  316.  
  317. void Unitdisk::copy_points(Unitdisk src) 
  318. {
  319.   set_divisions(src.rdivisions, src.tdivisions);
  320.   alloc_points();
  321.   copy_either(points, src.points);
  322. }
  323.  
  324. void Unitdisk::copy_normals(Unitdisk src) 
  325. {
  326.   set_divisions(src.rdivisions, src.tdivisions);
  327.   alloc_normals();
  328.   copy_either(normals, src.normals);
  329. }
  330.  
  331. void Unitdisk::copy_either(Point_b *dpt, Point_b *spt) {
  332.   int i, npoints;
  333.   npoints = get_npoints();
  334.   for (i = 0; i < npoints; i++, dpt++, spt++) {
  335.     dpt->pt[0] = spt->pt[0];
  336.     dpt->pt[1] = spt->pt[1];
  337.     dpt->pt[2] = spt->pt[2];
  338.   }
  339. }  
  340.  
  341. void Unitdisk::copy_normals_from_points(Unitdisk src) {
  342.   set_divisions(src.rdivisions, src.tdivisions);
  343.   alloc_normals();
  344.   copy_either(normals, src.points);
  345. }
  346.  
  347. void Unitdisk::copy_normals_from_points() {
  348.   copy_normals_from_points(*this);
  349. }
  350.  
  351. void Unitdisk::fill_either(Point_b *what) {
  352.   int t, r;
  353.   int i;
  354.  
  355.   fill_either_strip1(what);
  356.   if (sintable == NULL) fill_trig_tables();
  357.   i = rdivisions + 1;
  358.   for (t = 1; t < tdivisions; t++) {
  359.     for (r = 0; r <= rdivisions; r++) {
  360.       what[i].pt[0] = costable[t] * what[r].pt[0];
  361.       what[i].pt[1] = sintable[t] * what[r].pt[0];
  362.       what[i].pt[2] = what[r].pt[2];
  363.       i++;
  364.     }
  365.   }
  366. }
  367.  
  368. void Unitdisk::fill_points_strip1()
  369. {
  370.   alloc_points();
  371.   fill_either_strip1(points);
  372. }
  373.  
  374. void Unitdisk::fill_either_strip1(Point_b *what) {
  375.   float radius, rinc;
  376.   int r;
  377.  
  378.   rinc = get_radius() / (float)rdivisions;
  379.   radius = 0.0;
  380.   for (r = 0; r <= rdivisions; r++, radius += rinc) {
  381.     what[r].pt[0] = radius;
  382.     what[r].pt[1] = 0;
  383.     // Round-off error avoidance hack
  384.     what[r].pt[2] = 1.0 - what[r].pt[0]*what[r].pt[0];
  385.     if (what[r].pt[2] > 0.0) what[r].pt[2] = sqrt(what[r].pt[2]);
  386.     else what[r].pt[2] = 0.0;
  387.  }   
  388. }
  389.  
  390. void Unitdisk::translate(Point_b trans)
  391. {
  392.   int i, npoints;
  393.   npoints = get_npoints();
  394.   for (i = 0; i < npoints; i++) {
  395.     points[i].pt[0] += trans.pt[0];
  396.     points[i].pt[1] += trans.pt[1];
  397.     points[i].pt[2] += trans.pt[2];
  398.   }
  399. }
  400.  
  401. void Unitdisk::scale(float s) 
  402. {
  403.   int i, npoints;
  404.   npoints = get_npoints();
  405.   for (i = 0; i < npoints; i++) {
  406.     points[i].pt[0] *= s;
  407.     points[i].pt[1] *= s;
  408.     points[i].pt[2] *= s;
  409.   }
  410. }
  411.  
  412. void Unitdisk::scale_translate(float s, Point_b trans) 
  413. {
  414.   int i, npoints;
  415.   npoints = get_npoints();
  416.   for (i = 0; i < npoints; i++) {
  417.     points[i].pt[0] = points[i].pt[0]*s + trans.pt[0];
  418.     points[i].pt[1] = points[i].pt[1]*s + trans.pt[1];
  419.     points[i].pt[2] = points[i].pt[2]*s + trans.pt[2];
  420.   }
  421. }
  422.  
  423. int Unitdisk::get_npoints() 
  424. {
  425.   return (rdivisions + 1) * tdivisions;
  426. }
  427.  
  428. void Unitdisk::project()
  429. {
  430.   int i, npoints;
  431.  
  432.   if (normals == NULL) {
  433.     fprintf(stderr, "Warning:  No normals defined when project() called.\n");
  434.     fill_normals();
  435.   }
  436.   if (points == NULL) fill_points();
  437.   npoints = get_npoints();
  438.   for (i = 0; i < npoints; i++) {
  439.     /* I'm not sure quite what the justification for this is, but it
  440.      * seems to work */
  441.     if (normals[i].pt[2] < 0.0) normals[i].pt[2] = -normals[i].pt[2];
  442.     points[i] = points[i].project_direction(normals[i]);
  443.   }
  444. }
  445.  
  446. void Unitdisk::project(Point_b projpt)
  447. {
  448.   int i, npoints = get_npoints();
  449.   float x, y, z;
  450.   Point_b *pt;
  451.  
  452.   if (points == NULL) fill_points();
  453.   x = projpt.pt[0];
  454.   y = projpt.pt[1];
  455.   z = projpt.pt[2];
  456.   pt = points;
  457.   for (i = 0; i < npoints; i++, pt++) pt->project_self(x, y, z);
  458. }
  459.  
  460. void Unitdisk::project_borrow_points(Unitdisk src) 
  461. {
  462.   int i, npoints = get_npoints();
  463.   Point_b *pt, *spt, *sn;
  464.   spt = src.points;
  465.   sn = normals;
  466.   alloc_points();
  467.   pt = points;
  468.   for (i = 0; i < npoints; i++, pt++, spt++, sn++) {
  469.     /* I'm not sure quite what the justification for this is, but it
  470.      * seems to work */
  471.     if (normals[i].pt[2] < 0.0) normals[i].pt[2] = -normals[i].pt[2];
  472.     pt->compute_projected(spt->pt[0], spt->pt[1], spt->pt[2], 
  473.               sn->pt[0], sn->pt[1], sn->pt[2]);
  474.   }
  475. }
  476.  
  477. void Unitdisk::refract_normals(Point_b light, GLfloat I)
  478. {
  479.   Point_b dlight;
  480.   float cos1, sin1, cos2, sin2;
  481.   int use_normals;
  482.   int r, t, i;
  483.  
  484.   if (points == NULL) {
  485.     fprintf(stderr, "Attempting to refract without points.\n");
  486.     fill_normals();
  487.   }
  488.  
  489.   use_normals = (normals != NULL);
  490.   alloc_normals();
  491.  
  492.   /* Do the theta = 0 diagonal */
  493.   for (r = 0; r <= rdivisions; r++) {
  494.     /* Find the original normal - use the unit of the points if there are
  495.      * no normals */
  496.     if (!use_normals) normals[r] = points[r].unit();
  497.  
  498.     /* Compute the direction to the light */
  499.     dlight = (light - points[r]).unit();
  500.  
  501.     /* Compute the cosine and the sine of the original angle */
  502.     cos1 = dlight.dot(normals[r]);
  503.     sin1 = 1.0 - cos1*cos1;
  504.     if (sin1 <= 0.0) continue;
  505.     sin1 = sqrt(sin1);
  506.  
  507.     /* Compute the cosine and the sine of the new angle */
  508.     sin2 = sin1 / I;
  509.     cos2 = sqrt(1.0 - sin2*sin2);
  510.  
  511.     /* Rotate the normal by the new sine and cosine */
  512.     normals[r] = normals[r].rotate_abouty(cos2, -sin2);
  513.   }
  514.  
  515.   /* Copy the rest of the rows from the current row */
  516.   i = rdivisions + 1;
  517.   if (sintable == NULL) fill_trig_tables();
  518.   for (t = 1; t < tdivisions; t++) {
  519.     for (r = 0; r <= rdivisions; r++) {
  520.       normals[i].pt[0] = costable[t] * normals[r].pt[0];
  521.       normals[i].pt[1] = sintable[t] * normals[r].pt[0];
  522.       normals[i].pt[2] = normals[r].pt[2];
  523.       i++;
  524.     }
  525.   }
  526.  
  527. }
  528.  
  529. void Unitdisk::face_direction(Point_b d)
  530. {
  531.   face_direction(d, *this);
  532. }
  533.  
  534. void Unitdisk::face_direction(Point_b d, Unitdisk src) 
  535. {
  536.   Point_b *spt, *dpt, *sn, *dn;
  537.   float sin1, cos1;
  538.   float x;
  539.   int npoints, i;
  540.  
  541.   if (d.pt[1]) {
  542.     fprintf(stderr, 
  543.         "Internal error:  Can't face in direction not in xz plane.");
  544.     return;
  545.   }
  546.  
  547.   cos1 = d.pt[2];
  548.   sin1 = d.pt[0];
  549.   
  550.   if (sin1 * sin1 > fudge) {
  551.     spt = src.points;
  552.     dpt = points;
  553.     sn = src.normals;
  554.     dn = normals;
  555.     /* Change this to be seperate loops for points&&normals, points, normals
  556.      * (faster than testing every iteration */
  557.     npoints = get_npoints();
  558.     for (i = 0; i < npoints; i++) {
  559.       if (points != NULL) {
  560.     x = spt->pt[0];
  561.     dpt->pt[0] = x*cos1 + spt->pt[2]*sin1;
  562.     dpt->pt[1] = spt->pt[1];
  563.     dpt->pt[2] = -x*sin1 + spt->pt[2]*cos1;
  564.     spt++; dpt++;
  565.       }
  566.       if (normals != NULL) {
  567.     x = sn->pt[0];
  568.     dn->pt[0] = x*cos1 + sn->pt[2]*sin1;
  569.     dn->pt[1] = sn->pt[1];
  570.     dn->pt[2] = -x*sin1 + sn->pt[2]*cos1;
  571.     sn++; dn++;
  572.       }
  573.     }
  574.   } else if (points != NULL && points != src.points) {
  575.     copy_points(src);
  576.     if (normals != NULL) copy_normals(src);
  577.   }
  578. }  
  579.  
  580. void Unitdisk::alloc_colors()
  581. {
  582.   int ncolors = get_npoints();
  583.   if (ncolors > colors_size) {
  584.     delete colors;
  585.     colors = new Color[ncolors];
  586.     colors_size = ncolors;
  587.   }
  588. }
  589.  
  590. void Unitdisk::map_normals_to_colors() 
  591. {
  592.   int t, r;
  593.   int i;
  594.  
  595.   if (normals == NULL) fill_normals();
  596.   alloc_colors();
  597.   i = 0;
  598.   for (t = 1; t <= tdivisions; t++) {
  599.     for (r = 0; r <= rdivisions; r++) {
  600.       colors[i] *= normals[r].pt[2];
  601.       colors[i].c[3] = 1;
  602.       i++;
  603.     }
  604.   }
  605. }
  606.  
  607. void Unitdisk::map_z_to_colors()
  608. {
  609.   int i, npoints = get_npoints();
  610.  
  611.   if (points == NULL) {
  612.     fprintf(stderr, "Warning:  no points defined in map_z_to_colors()\n");
  613.     fill_points();
  614.   }
  615.  
  616.   alloc_colors();
  617.   for (i = 0; i < npoints; i++) {
  618.     colors[i] = points[i].pt[2];
  619.     colors[i].c[3] = 1;
  620.   }
  621. }
  622.  
  623. void Unitdisk::scale_alpha_by_z()
  624. {
  625.   int i, npoints = get_npoints();
  626.   
  627.   if (colors == NULL) alloc_colors();
  628.   if (points == NULL) {
  629.     alloc_points();
  630.     fill_points();
  631.   }
  632.   for (i = 0; i < npoints; i++) colors[i].c[3] *= points[i].pt[2];
  633. }
  634.  
  635. void Unitdisk::scale_colors_by_z() 
  636. {
  637.   int i, npoints = get_npoints();
  638.  
  639.   if (colors == NULL) alloc_colors();
  640.   if (points == NULL) {
  641.     alloc_points();
  642.     fill_points();
  643.   }
  644.   for (i = 0; i < npoints; i++) colors[i] *= points[i].pt[2];
  645. }
  646.  
  647. void Unitdisk::scale_colors_by_normals(Point_b light)
  648. {
  649.   scale_colors_by_normals(light, *this);
  650. }
  651.  
  652. void Unitdisk::scale_colors_by_normals(Point_b light, Unitdisk src_normals)
  653. {
  654.   scale_colors_by_either(light, src_normals.normals);
  655. }
  656.  
  657. void Unitdisk::scale_colors_by_points(Point_b light, Unitdisk src_points)
  658. {
  659.   scale_colors_by_either(light, src_points.points);
  660. }
  661.  
  662. void Unitdisk::scale_colors_by_either(Point_b light, Point_b *what)
  663. {
  664.   int t, r;
  665.   int i;
  666.   if (what == NULL) {
  667.     fprintf(stderr, "Scaling colors to NULL pointer.\n");
  668.     return;
  669.   }
  670.   if (light.pt[0] || light.pt[1] || light.pt[2] < 0.0) {
  671.     fprintf(stderr, "Light not on z axis in scale_colors_by_normals.\n");
  672.   }
  673.  
  674.   alloc_colors();
  675.   for (r = 0; r <= rdivisions; r++) 
  676.     colors[r] *= what[r].dot(light);
  677.   i = rdivisions + 1;
  678.   for (t = 1; t < tdivisions; t++) {
  679.     for (r = 0; r <= rdivisions; r++) {
  680.       colors[i] = colors[r];
  681.       i++;
  682.     }
  683.   }
  684. }  
  685.  
  686. void Unitdisk::set_colors(Color c)
  687. {
  688.   Color *dst;
  689.   int i, npoints = get_npoints();
  690.   alloc_colors();
  691.   dst = colors;
  692.   for (i = 0; i < npoints; i++, dst++) {
  693.     dst->c[0] = c.c[0];
  694.     dst->c[1] = c.c[1];
  695.     dst->c[2] = c.c[2];
  696.     dst->c[3] = c.c[3];
  697.   }
  698. }
  699.  
  700. void Unitdisk::add_colors(Color c)
  701. {
  702.   int i, npoints = get_npoints();
  703.   alloc_colors();
  704.   for (i = 0; i < npoints; i++) colors[i] += c;
  705. }
  706.  
  707. void Unitdisk::free_colors()
  708. {
  709.   delete colors;
  710.   colors = NULL;
  711.   colors_size = 0;
  712. }
  713.  
  714. inline float Unitdisk::area_triangle(Point_b a, Point_b b, Point_b c)
  715. {
  716.   return (((a.pt[0]*b.pt[1] + b.pt[0]*c.pt[1] + c.pt[0]*a.pt[1]) -
  717.        (a.pt[1]*b.pt[0] + b.pt[1]*c.pt[0] + c.pt[1]*a.pt[0])) * .5);
  718. }
  719.  
  720. inline float Unitdisk::area_triangle(GLfloat *a, GLfloat *b, 
  721.                      GLfloat *c) 
  722. {
  723.   return (((a[0]*b[1] + b[0]*c[1] + c[0]*a[1]) -
  724.        (a[1]*b[0] + b[1]*c[0] + c[1]*a[0])) * .5);
  725. }
  726.  
  727. inline float Unitdisk::area_2triangle(GLfloat *a, GLfloat *b, 
  728.                      GLfloat *c) 
  729. {
  730.   return ((a[0]*b[1] + b[0]*c[1] + c[0]*a[1]) -
  731.       (a[1]*b[0] + b[1]*c[0] + c[1]*a[0]));
  732. }
  733.  
  734. void Unitdisk::scale_colors_by_darea(Unitdisk disk) 
  735. {
  736.   int pt1, pt2, pt3;
  737.   int t, r, i;
  738.   int npoints = get_npoints();
  739.   float *rproducts1, *tproducts1, *rproducts2, *tproducts2;
  740.   float area1, area2;
  741.  
  742.   rproducts1 = new float[npoints];
  743.   tproducts1 = new float[npoints];
  744.   rproducts2 = new float[npoints];
  745.   tproducts2 = new float[npoints];
  746.  
  747.   /* Compute the products of the segments which make up the disk - 
  748.    * these will later be used in the area calculations */
  749.   i = 0;
  750.   for (t = 0; t < tdivisions; t++) {
  751.     for (r = 0; r < rdivisions; r++) {
  752.       pt1 = i;
  753.       pt2 = i + 1;
  754.       rproducts1[i] = (points[pt1].pt[0]*points[pt2].pt[1] -
  755.                points[pt1].pt[1]*points[pt2].pt[0]);
  756.       rproducts2[i] = (disk.points[pt1].pt[0]*disk.points[pt2].pt[1] - 
  757.                disk.points[pt1].pt[1]*disk.points[pt2].pt[0]);
  758.       pt2 = ((t+1)%tdivisions)*(rdivisions + 1) + r;
  759.       tproducts1[i] = (points[pt1].pt[0]*points[pt2].pt[1] -
  760.                points[pt1].pt[1]*points[pt2].pt[0]);
  761.       tproducts2[i] = (disk.points[pt1].pt[0]*disk.points[pt2].pt[1] - 
  762.                disk.points[pt1].pt[1]*disk.points[pt2].pt[0]);
  763.       i++;
  764.     }
  765.     pt1 = i;
  766.     pt2 = ((t+1)%tdivisions)*(rdivisions + 1) + r;
  767.     tproducts1[i] = (points[pt1].pt[0]*points[pt2].pt[1] -
  768.              points[pt1].pt[1]*points[pt2].pt[0]);
  769.     tproducts2[i] = (disk.points[pt1].pt[0]*disk.points[pt2].pt[1] - 
  770.              disk.points[pt1].pt[1]*disk.points[pt2].pt[0]);
  771.     i++;
  772.   }
  773.  
  774.   /* Compute the area at the center of the disk */
  775.   area1 = area2 = 0.0;
  776.   r = 1;
  777.   for (t = 0; t <= tdivisions; t++) {
  778.     pt1 = (t%tdivisions)*(rdivisions+1) + r;
  779.     area1 += tproducts1[pt1];
  780.     area2 += tproducts2[pt1];
  781.   }
  782.   if (area1 != 0.0) area1 = fabs(area2 / area1);
  783.   for (t = 0; t < tdivisions; t++) {
  784.     colors[t*(rdivisions+1)] *= area1;
  785.   }
  786.  
  787.   for (t = 0; t < tdivisions; t++) {
  788.     for (r = 1; r < rdivisions; r++) {
  789.       pt1 = (t ? t-1 : tdivisions-1)*(rdivisions+1) + r - 1;
  790.       pt3 = t*(rdivisions + 1) + r - 1;
  791.       pt2 = ((t+1) % tdivisions)*(rdivisions+1) + r - 1;
  792.       area1 = rproducts1[pt1] + rproducts1[pt1 + 1];
  793.       area1 += tproducts1[pt1 + 2] + tproducts1[pt3 + 2];
  794.       area1 -= rproducts1[pt2 + 1] + rproducts1[pt2];
  795.       area1 -= tproducts1[pt3] + tproducts1[pt1];
  796.       area2 = rproducts2[pt1] + rproducts2[pt1 + 1];
  797.       area2 += tproducts2[pt1 + 2] + tproducts2[pt3 + 2];
  798.       area2 -= rproducts2[pt2 + 1] + rproducts2[pt2];
  799.       area2 -= tproducts2[pt3] + tproducts2[pt1];
  800.       if (area1 != 0.0) area1 = fabs(area2 / area1);
  801.       colors[pt3 + 1] *= area1;
  802.     }
  803.   }
  804.  
  805.   /* Compute the area around the outside of the disk */
  806.   r = rdivisions;
  807.   for (t = 0; t < tdivisions; t++) {
  808.     pt1 = (t ? t-1 : tdivisions-1)*(rdivisions+1) + r - 1;
  809.     pt3 = t*(rdivisions + 1) + r - 1;
  810.     pt2 = ((t+1) % tdivisions)*(rdivisions+1) + r - 1;
  811.     area1 = rproducts1[pt1];
  812.     area1 += tproducts1[pt1 + 1] + tproducts1[pt3 + 1];
  813.     area1 -= rproducts1[pt2];
  814.     area1 -= tproducts1[pt1] + tproducts1[pt3];
  815.     area2 = rproducts2[pt1];
  816.     area2 += tproducts2[pt1 + 1] + tproducts2[pt3 + 1];
  817.     area2 -= rproducts2[pt2];
  818.     area2 -= tproducts2[pt1] + tproducts2[pt3];
  819.     if (area1 != 0.0) area1 = fabs(area2 / area1);
  820.     colors[pt3 + 1] *= area1;
  821.   }
  822.  
  823.  
  824.   delete rproducts1;
  825.   delete tproducts1;
  826.   delete rproducts2;
  827.   delete tproducts2;
  828. }
  829.  
  830. void Unitdisk::fill_trig_tables()
  831. {
  832.   int t;
  833.  
  834.   delete sintable;
  835.   delete costable;
  836.   sintable = new float[tdivisions];
  837.   costable = new float[tdivisions];
  838.   for (t = 0; t < tdivisions; t++) {
  839.     costable[t] = cos(M_2PI * (float)t / (float)tdivisions);
  840.     sintable[t] = sin(M_2PI * (float)t / (float)tdivisions);
  841.   }
  842. }
  843.